#ifndef SIFTGEO_H
#define SIFTGEO_H
#include "configure.h"
#include <iostream>
#include <sys/mman.h>
#include <unistd.h>
#include <ctime>
#include <boost/filesystem.hpp>
#include <fcntl.h>
using std::string;
using std::ostream;
using std::endl;
using std::cout;
namespace bfs = boost::filesystem;
const string EXE_PATH ="/home/cvhadoop/imr/extract_features/";

class SiftGeo
{
    public:
    int count;
    float *geo_x,*geo_y,*geo_scale,*geo_angle;
    float *sift;
    string name;
    SiftGeo(int num = MAXRECORDS_PER_SIFTGEO)
    {
        cout << "siftgeo constructor " << endl;
        count = 0;
        geo_x = new float[num];
        geo_y = new float[num];
        geo_scale = new float[num];
        geo_angle = new float[num];
        sift = new float[SIFT_DIM*num];
        name = "tmp";
    }
    void free()
    {
        delete[] geo_x;
        delete[] geo_y;
        delete[] geo_scale;
        delete[] geo_angle;
        delete[] sift;
    }
    ~SiftGeo()
    {
        cout << " siftgeo destructor " << endl;

    }
    int fromfile(string filename,float* geo_x ,float* geo_y,float* geo_scale ,float* geo_angle,float* sift)
    {
        cout << filename << endl;
        name = filename;
        struct stat statbuf;
        stat(filename.c_str(),&statbuf);
        int bytenum = statbuf.st_size;
        int fid = open(filename.c_str(),O_RDONLY);
        char *back_buf = reinterpret_cast<char*>(mmap(NULL,bytenum,PROT_READ,MAP_PRIVATE,fid,0));
        float* buf = reinterpret_cast<float*>(back_buf);
        unsigned char* siftbuf = reinterpret_cast<unsigned char*>(back_buf);
        int step = 9*sizeof(float) + sizeof(int) + SIFT_DIM * sizeof(char);
        float* siftptr = sift;
        count = 0;
        while(bytenum > 0)
        {
            geo_x[count] = *(buf++);
            geo_y[count] = *(buf++);
            geo_scale[count] = *(buf++);
            geo_angle[count] = *(buf++);
            buf += 6;   //emit 6 values
            siftbuf = reinterpret_cast<unsigned char*>(buf);
            for(int i=0; i<SIFT_DIM; ++i,++siftbuf,++siftptr)
            *siftptr = *siftbuf;
            buf = reinterpret_cast<float*>(siftbuf);
            ++count;
            bytenum -= step;
        }
        munmap(back_buf,statbuf.st_size);
        close(fid);
        return count;
    }
    int fromfile(string filename)
    {
        return fromfile(filename,this->geo_x,this->geo_y,this->geo_scale,this->geo_angle,this->sift);
    }
    int fromimage(string imagename)
    {
        bfs::path imagepath(imagename);

    }
    int tofile()
    {
        FILE* fid = fopen(name.c_str(),"w");

    }
};

ostream& operator<<(ostream& os,SiftGeo &sg)
{
    for(int i=0,s=0; i<sg.count; ++i)
    {
        os << " geo_x = " << sg.geo_x[i];
        os << " geo_y = " << sg.geo_y[i];
        os << " geo_sacle = " << sg.geo_scale[i];
        os << " geo_angle = " << sg.geo_angle[i] << endl;
        os << " sift :: ";
        for(int j=0; j<SIFT_DIM; ++j,++s)
            os << sg.sift[s] <<", ";
        os << endl;
    }
    return os;
}
void test_siftgeo(string siftgeo_path = SIFTGEO_PATH)
{
    bfs::path siftdir(siftgeo_path);
    SiftGeo sg(50000);
    int start = clock();
    for(bfs::directory_iterator dit(siftdir); dit!=bfs::directory_iterator(); ++dit)
    {
        sg.fromfile((*dit).string());
        cout << (*dit).string() <<endl;
        cout << sg;
    }
    sg.free();
    cout << " time is " << clock() - start<<endl;
}

#endif
